/* Copyright (c) 2006 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/
/* Change history
* Oct 13 2008  Joe Feser       joseph.feser@gmail.com
* Converted ArrayLists and other .NET 1.1 collections to use Generics
* Combined IExtensionElement and IExtensionElementFactory interfaces
* 
*/

#define USE_TRACING

using System;
using Google.GData.Client;
using Google.GData.Extensions;


namespace Google.GData.Contacts {

    /// <summary>
    /// short table to hold the namespace and the prefix
    /// </summary>
    public class ContactsNameTable 
    {
        /// <summary>static string to specify the Contacts namespace supported</summary>
        public const string NSContacts = "http://schemas.google.com/contact/2008"; 
        /// <summary>static string to specify the Google Contacts prefix used</summary>
        public const string contactsPrefix = "gContact"; 

        /// <summary>
        /// Group Member ship info element string
        /// </summary>
        public const string GroupMembershipInfo = "groupMembershipInfo";

        /// <summary>
        /// SystemGroup element, indicating that this entry is a system group
        /// </summary>
        public const string SystemGroupElement = "systemGroup";

        /// <summary>
        /// Specifies billing information of the entity represented by the contact. The element cannot be repeated
        /// </summary>
        public const string BillingInformationElement = "billingInformation";

        /// <summary>
        /// Stores birthday date of the person represented by the contact. The element cannot be repeated
        /// </summary>
        public const string BirthdayElement = "birthday";

        /// <summary>
        /// Storage for URL of the contact's calendar. The element can be repeated
        /// </summary>
        public const string CalendarLinkElement = "calendarLink";

        /// <summary>
        /// A directory server associated with this contact. May not be repeated
        /// </summary>
        public const string DirectoryServerElement = "directoryServer";

        /// <summary>
        /// An event associated with a contact. May be repeated.
        /// </summary>
        public const string EventElement = "event";

        /// <summary>
        /// Describes an ID of the contact in an external system of some kind. This element may be repeated.
        /// </summary>
        public const string ExternalIdElement = "externalId";

        /// <summary>
        /// Specifies the gender of the person represented by the contact. The element cannot be repeated.
        /// </summary>
        public const string GenderElement = "gender";

        /// <summary>
        /// Specifies hobbies or interests of the person specified by the contact. The element can be repeated
        /// </summary>
        public const string HobbyElement = "hobby";

        /// <summary>
        /// Specifies the initials of the person represented by the contact. The element cannot be repeated.
        /// </summary>
        public const string InitialsElement = "initials";

        /// <summary>
        /// Storage for arbitrary pieces of information about the contact. Each jot has a type specified by the rel attribute and a text value. The element can be repeated.
        /// </summary>
        public const string JotElement = "jot";

        /// <summary>
        /// Specifies the preferred languages of the contact. The element can be repeated
        /// </summary>
        public const string LanguageElement = "language";

        /// <summary>
        /// Specifies maiden name of the person represented by the contact. The element cannot be repeated.
        /// </summary>
        public const string MaidenNameElement = "maidenName";

        /// <summary>
        /// Specifies the mileage for the entity represented by the contact. Can be used for example to document distance needed for reimbursement purposes. 
        /// The value is not interpreted. The element cannot be repeated
        /// </summary>
        public const string MileageElement = "mileage";

        /// <summary>
        /// Specifies the nickname of the person represented by the contact. The element cannot be repeated
        /// </summary>
        public const string NicknameElement = "nickname";

        /// <summary>
        /// Specifies the occupation/profession of the person specified by the contact. The element cannot be repeated.
        /// </summary>
        public const string OccupationElement = "occupation";
        
        /// <summary>
        /// Classifies importance into 3 categories. can not be repeated
        /// </summary>
        public const string PriorityElement = "priority";

        /// <summary>
        /// Describes the relation to another entity. maybe repeated
        /// </summary>
        public const string RelationElement = "relation";

        /// <summary>
        /// Classifies sensitifity of the contact
        /// </summary>
        public const string SensitivityElement = "sensitivity";
        
        /// <summary>
        /// Specifies short name of the person represented by the contact. The element cannot be repeated.
        /// </summary>
        public const string ShortNameElement = "shortName";
        
        /// <summary>
        /// Specifies the subject of the contact. The element cannot be repeated.
        /// </summary>
        public const string SubjectElement = "subject";
        
        /// <summary>
        /// Represents an arbitrary key-value pair attached to the contact.
        /// </summary>
        public const string UserDefinedFieldElement = "userDefinedField";
        
        /// <summary>
        /// Websites associated with the contact. Maybe repeated
        /// </summary>
        public const string WebsiteElement = "website";
        
        /// <summary>
        /// rel Attribute
        /// </summary>
        /// <returns></returns>
        public static string AttributeRel = "rel";
        /// <summary>
        /// label Attribute
        /// </summary>
        /// <returns></returns>
        public static string AttributeLabel = "label";
   }



    /// <summary>
    /// an element is defined that represents a group to which the contact belongs   
    /// </summary>
    public class GroupMembership: SimpleElement
    {
        /// <summary>the  href attribute </summary>
        public const string XmlAttributeHRef = "href";
        /// <summary>the deleted attribute </summary>
        public const string XmlAttributeDeleted = "deleted";

        /// <summary>
        /// default constructor 
        /// </summary>
        public GroupMembership()
        : base(ContactsNameTable.GroupMembershipInfo, ContactsNameTable.contactsPrefix, ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(XmlAttributeHRef, null);
            this.Attributes.Add(XmlAttributeDeleted, null);
        }

       /////////////////////////////////////////////////////////////////////
       /// <summary>Identifies the group to which the contact belongs or belonged. 
       /// The group is referenced by its id.</summary>
       //////////////////////////////////////////////////////////////////////
       public string HRef
       {
           get
           {
               return this.Attributes[XmlAttributeHRef] as string;
           }
           set
           {
               this.Attributes[XmlAttributeHRef] = value;
           }
       }

       /////////////////////////////////////////////////////////////////////
       /// <summary>Means, that the group membership was removed for the contact. 
       /// This attribute will only be included if showdeleted is specified 
       /// as query parameter, otherwise groupMembershipInfo for groups a contact 
       /// does not belong to anymore is simply not returned.</summary>
       //////////////////////////////////////////////////////////////////////
       public string Deleted
       {
           get
           {
               return this.Attributes[XmlAttributeDeleted] as string;
           }
       }
    }


    /// <summary>
    /// extension element to represent a system group
    /// </summary>
    public class SystemGroup : SimpleElement
    {
        /// <summary>
        /// id attribute for the system group element
        /// </summary>
        /// <returns></returns>
        public const string XmlAttributeId = "id";

        /// <summary>
        /// default constructor 
        /// </summary>
        public SystemGroup()
        : base(ContactsNameTable.SystemGroupElement, ContactsNameTable.contactsPrefix, ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(XmlAttributeId, null);
        }

       /////////////////////////////////////////////////////////////////////
       /// <summary>Identifies the system group. Note that you still need 
       /// to use the group entries href membership to retrieve the group
       /// </summary>
       //////////////////////////////////////////////////////////////////////
       public string Id
       {
           get
           {
               return this.Attributes[XmlAttributeId] as string;
           }
       }
    }

    /// <summary>
    /// abstract class for a basecontactentry, used for contacts and groups
    /// </summary>
    public abstract class BaseContactEntry : AbstractEntry, IContainsDeleted
    {
        private ExtensionCollection<ExtendedProperty> xproperties;


        /// <summary>
        /// Constructs a new BaseContactEntry instance 
        /// to indicate that it is an event.
        /// </summary>
        public BaseContactEntry()
        : base()
        {
            Tracing.TraceMsg("Created BaseContactEntry Entry");
            this.AddExtension(new ExtendedProperty());
            this.AddExtension(new Deleted());
        }


        /// <summary>
        /// returns the extended properties on this object
        /// </summary>
        /// <returns></returns>
        public ExtensionCollection<ExtendedProperty> ExtendedProperties
        {
            get 
            {
                if (this.xproperties == null)
                {
                    this.xproperties = new ExtensionCollection<ExtendedProperty>(this); 
                }
                return this.xproperties;
            }
        }


        /// <summary>
        /// if this is a previously deleted contact, returns true
        /// to delete a contact, use the delete method
        /// </summary>
        public bool Deleted
        {
            get
            {
                if (FindExtension(GDataParserNameTable.XmlDeletedElement,
                                     BaseNameTable.gNamespace) != null) 
                {
                    return true;
                }
                return false;
            }
        }
    }



    /// <summary>
    /// Specifies billing information of the entity represented by the contact. The element cannot be repeated
    /// </summary>
    public class BillingInformation : SimpleElement
    {
        /// <summary>
        /// default constructor for BillingInformation
        /// </summary>
        public BillingInformation()
            : base(ContactsNameTable.BillingInformationElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for BillingInformation with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public BillingInformation(string initValue)
            : base(ContactsNameTable.BillingInformationElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Stores birthday date of the person represented by the contact. The element cannot be repeated.
    /// </summary>
    public class Birthday : SimpleElement
    {

        /// <summary>
        /// When Attribute
        /// </summary>
        /// <returns></returns>
        public static string AttributeWhen = "when";

        /// <summary>
        /// default constructor for Birthday
        /// </summary>
        public Birthday()
            : base(ContactsNameTable.BirthdayElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(AttributeWhen, null);
        }
    
        /// <summary>
        /// default constructor for Birthday with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Birthday(string initValue)
            : base(ContactsNameTable.BirthdayElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(AttributeWhen, initValue);
        }

        //////////////////////////////////////////////////////////////////////
        /// <summary>Birthday date, given in format YYYY-MM-DD (with the year), or --MM-DD (without the year)</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string When
        {
           get 
            {
                return this.Attributes[AttributeWhen] as string;
            }
            set
            {
                this.Attributes[AttributeWhen] = value;
            }
        }
    }


  


     /// <summary>
    /// Storage for URL of the contact's information. The element can be repeated.
    /// </summary>
    public class ContactsLink : LinkAttributesElement
    {
        /// <summary>
        /// href Attribute
        /// </summary>
        /// <returns></returns>
        public static string AttributeHref = "href";

        /// <summary>
        /// default constructor for CalendarLink
        /// </summary>
        public ContactsLink(string elementName, string elementPrefix, string elementNamespace)
            : base(elementName, elementPrefix, elementNamespace)
        {
             this.Attributes.Add(AttributeHref, null);
        }
    
    
     
        //////////////////////////////////////////////////////////////////////
        /// <summary>The URL of the the related link.</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Href
        {
           get 
            {
                return this.Attributes[AttributeHref] as string;
            }
            set
            {
                this.Attributes[AttributeHref] = value;
            }
        }
    }
  


    /// <summary>
    /// Storage for URL of the contact's calendar. The element can be repeated.
    /// </summary>
    public class CalendarLink : ContactsLink
    {
       public CalendarLink()
            : base(ContactsNameTable.CalendarLinkElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            
        }
    }
  
    
    /// <summary>
    /// DirectoryServer schema extension 
    /// </summary>
    public class DirectoryServer : SimpleElement
    {
        /// <summary>
        /// default constructor for DirectoryServer
        /// </summary>
        public DirectoryServer()
            : base(ContactsNameTable.DirectoryServerElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for DirectoryServer with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public DirectoryServer(string initValue)
            : base(ContactsNameTable.DirectoryServerElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Event schema extension 
    /// </summary>
    public class Event : SimpleContainer
    {
        /// <summary>
        /// default constructor for Event
        /// </summary>
        public Event()
            : base(ContactsNameTable.EventElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
       {              
            this.Attributes.Add(ContactsNameTable.AttributeRel, null);
            this.Attributes.Add(ContactsNameTable.AttributeLabel, null);
            this.ExtensionFactories.Add(new When());
        }
    
        //////////////////////////////////////////////////////////////////////
        /// <summary>Predefined calendar link type. Can be one of work, home or free-busy</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Relation
        {
           get 
            {
                return this.Attributes[ContactsNameTable.AttributeRel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeRel] = value;
            }
        }

        //////////////////////////////////////////////////////////////////////
        /// <summary>User-defined calendar link type.</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Label
        {
            get 
            {
                return this.Attributes[ContactsNameTable.AttributeLabel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeLabel] = value;
            }
        }

        /// <summary>
        /// exposes the When element for this event
        /// </summary>
        /// <returns></returns>
        public When When
        {
            get
            {
                return FindExtension(GDataParserNameTable.XmlWhenElement,
                                     BaseNameTable.gNamespace) as When;
            }
            set
            {
                ReplaceExtension(GDataParserNameTable.XmlWhenElement,
                                 BaseNameTable.gNamespace,
                                 value);
            }
        }

      
    }

    /// <summary>
    /// ExternalId schema extension 
    /// </summary>
    public class ExternalId : SimpleAttribute
    {
        /// <summary>
        /// default constructor for ExternalId
        /// </summary>
        public ExternalId()
            : base(ContactsNameTable.ExternalIdElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeRel, null);
            this.Attributes.Add(ContactsNameTable.AttributeLabel, null);
 
        }
    
        /// <summary>
        /// default constructor for ExternalId with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public ExternalId(string initValue)
            : base(ContactsNameTable.ExternalIdElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
            this.Attributes.Add(ContactsNameTable.AttributeRel, null);
            this.Attributes.Add(ContactsNameTable.AttributeLabel, null);
        }

         //////////////////////////////////////////////////////////////////////
        /// <summary>Predefined calendar link type. Can be one of work, home or free-busy</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Relation
        {
           get 
            {
                return this.Attributes[ContactsNameTable.AttributeRel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeRel] = value;
            }
        }

        //////////////////////////////////////////////////////////////////////
        /// <summary>User-defined calendar link type.</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Label
        {
            get 
            {
                return this.Attributes[ContactsNameTable.AttributeLabel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeLabel] = value;
            }
        }
    }

    /// <summary>
    /// Gender schema extension 
    /// </summary>
    public class Gender : SimpleAttribute
    {
        /// <summary>
        /// default constructor for Gender
        /// </summary>
        public Gender()
            : base(ContactsNameTable.GenderElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for Gender with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Gender(string initValue)
            : base(ContactsNameTable.GenderElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Hobby schema extension 
    /// </summary>
    public class Hobby : SimpleElement
    {
        /// <summary>
        /// default constructor for Hobby
        /// </summary>
        public Hobby()
            : base(ContactsNameTable.HobbyElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for Hobby with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Hobby(string initValue)
            : base(ContactsNameTable.HobbyElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Initials schema extension 
    /// </summary>
    public class Initials : SimpleElement
    {
        /// <summary>
        /// default constructor for Initials
        /// </summary>
        public Initials()
            : base(ContactsNameTable.InitialsElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for Initials with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Initials(string initValue)
            : base(ContactsNameTable.InitialsElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Jot schema extension 
    /// </summary>
    public class Jot : SimpleElement
    {
        /// <summary>
        /// default constructor for Jot
        /// </summary>
        public Jot()
            : base(ContactsNameTable.JotElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeRel, null);
        }
    
 
        //////////////////////////////////////////////////////////////////////
        /// <summary>Predefined calendar link type. Can be one of work, home or free-busy</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Relation
        {
           get 
            {
                return this.Attributes[ContactsNameTable.AttributeRel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeRel] = value;
            }
        }

    }

    /// <summary>
    /// Language schema extension 
    /// </summary>
    public class Language : SimpleElement
    {
        /// <summary>
        /// the code attribute
        /// </summary>
        /// <returns></returns>
        public static string AttributeCode = "code";

        /// <summary>
        /// default constructor for Language
        /// </summary>
        public Language()
            : base(ContactsNameTable.LanguageElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeLabel, null);
            this.Attributes.Add(AttributeCode, null);
        }
    
        /// <summary>
        /// default constructor for Language with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Language(string initValue)
            : base(ContactsNameTable.LanguageElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
            this.Attributes.Add(ContactsNameTable.AttributeLabel, null);
            this.Attributes.Add(AttributeCode, null);
        }

        //////////////////////////////////////////////////////////////////////
        /// <summary>A freeform name of a language. Must not be empty or all whitespace..</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Label
        {
            get 
            {
                return this.Attributes[ContactsNameTable.AttributeLabel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeLabel] = value;
            }
        }


        //////////////////////////////////////////////////////////////////////
        /// <summary>A language code conforming to the IETF BCP 47 specification. .</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Code
        {
            get 
            {
                return this.Attributes[AttributeCode] as string;
            }
            set
            {
                this.Attributes[AttributeCode] = value;
            }
        }
    }

    /// <summary>
    /// Specifies maiden name of the person represented by the contact. The element cannot be repeated.
    /// </summary>
    public class MaidenName : SimpleElement
    {
        /// <summary>
        /// default constructor for MaidenName
        /// </summary>
        public MaidenName()
            : base(ContactsNameTable.MaidenNameElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for MaidenName with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public MaidenName(string initValue)
            : base(ContactsNameTable.MaidenNameElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Specifies the mileage for the entity represented by the contact. Can be used for example to 
    /// document distance needed for reimbursement purposes. The value is not interpreted. The element cannot be repeated.
    /// </summary>
    public class Mileage : SimpleElement
    {
        /// <summary>
        /// default constructor for Mileage
        /// </summary>
        public Mileage()
            : base(ContactsNameTable.MileageElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for Mileage with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Mileage(string initValue)
            : base(ContactsNameTable.MileageElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Specifies the nickname of the person represented by the contact. The element cannot be repeated
    /// </summary>
    public class Nickname : SimpleElement
    {
        /// <summary>
        /// default constructor for Nickname
        /// </summary>
        public Nickname()
            : base(ContactsNameTable.NicknameElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for Nickname with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Nickname(string initValue)
            : base(ContactsNameTable.NicknameElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Specifies the occupation/profession of the person specified by the contact. The element cannot be repeated.
    /// </summary>
    public class Occupation : SimpleElement
    {
        /// <summary>
        /// default constructor for Occupation
        /// </summary>
        public Occupation()
            : base(ContactsNameTable.OccupationElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {

        }
    
        /// <summary>
        /// default constructor for Occupation with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Occupation(string initValue)
            : base(ContactsNameTable.OccupationElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Classifies importance of the contact into 3 categories, low, normal and high
    /// </summary>
    public class Priority : SimpleElement
    {
        /// <summary>
        /// default constructor for Priority
        /// </summary>
        public Priority()
            : base(ContactsNameTable.PriorityElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeRel, null);
        }

        /// <summary>
        /// default constructor for Priority with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Priority(string initValue)
            : base(ContactsNameTable.OccupationElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeRel, initValue);
        }
    
        //////////////////////////////////////////////////////////////////////
        /// <summary>Predefined calendar link type. Can be one of work, home or free-busy</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Relation
        {
           get 
            {
                return this.Attributes[ContactsNameTable.AttributeRel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeRel] = value;
            }
        }
    }


   
    /// <summary>
    /// Relation schema extension 
    /// </summary>
    public class Relation : SimpleElement
    {
        /// <summary>
        /// default constructor for Relation
        /// </summary>
        public Relation()
            : base(ContactsNameTable.RelationElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeLabel, null);
            this.Attributes.Add(ContactsNameTable.AttributeRel, null);
       }
    
         //////////////////////////////////////////////////////////////////////
        /// <summary>A freeform name of a language. Must not be empty or all whitespace..</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Label
        {
            get 
            {
                return this.Attributes[ContactsNameTable.AttributeLabel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeLabel] = value;
            }
        }

         //////////////////////////////////////////////////////////////////////
        /// <summary>defines the link type.</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Rel
        {
           get 
            {
                return this.Attributes[ContactsNameTable.AttributeRel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeRel] = value;
            }
        }
    }

    /// <summary>
    /// Classifies sensitivity of the contact into the following categories:
    /// confidential, normal, personal or private
    /// </summary>
    public class Sensitivity : SimpleElement
    {
        /// <summary>
        /// default constructor for Sensitivity
        /// </summary>
        public Sensitivity()
            : base(ContactsNameTable.SensitivityElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeRel, null);
        }

        /// <summary>
        /// default constructor for Sensitivity with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Sensitivity(string initValue)
            : base(ContactsNameTable.OccupationElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(ContactsNameTable.AttributeRel, initValue);
        }
    
        //////////////////////////////////////////////////////////////////////
        /// <summary>returns the relationship value</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Relation
        {
           get 
            {
                return this.Attributes[ContactsNameTable.AttributeRel] as string;
            }
            set
            {
                this.Attributes[ContactsNameTable.AttributeRel] = value;
            }
        }
    }


    /// <summary>
    /// Specifies short name of the person represented by the contact. The element cannot be repeated.
    /// </summary>
    public class ShortName : SimpleElement
    {
        /// <summary>
        /// default constructor for ShortName
        /// </summary>
        public ShortName()
            : base(ContactsNameTable.ShortNameElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for ShortName with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public ShortName(string initValue)
            : base(ContactsNameTable.ShortNameElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Specifies the subject of the contact. The element cannot be repeated.
    /// </summary>
    public class Subject : SimpleElement
    {
        /// <summary>
        /// default constructor for Subject
        /// </summary>
        public Subject()
            : base(ContactsNameTable.SubjectElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
    
        /// <summary>
        /// default constructor for Subject with an initial value
        /// </summary>
        /// <param name="initValue"/>
        public Subject(string initValue)
            : base(ContactsNameTable.SubjectElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
        }
    }

    /// <summary>
    /// Represents an arbitrary key-value pair attached to the contact.
    /// </summary>
    public class UserDefinedField : SimpleAttribute
    {
        /// <summary>
        /// key attribute
        /// </summary>
        /// <returns></returns>
        public static string AttributeKey = "key";

        /// <summary>
        /// default constructor for UserDefinedField
        /// </summary>
        public UserDefinedField()
            : base(ContactsNameTable.UserDefinedFieldElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
            this.Attributes.Add(AttributeKey, null);   
        }
    
        /// <summary>
        /// default constructor for UserDefinedField with an initial value
        /// </summary>
        /// <param name="initValue"/>
        /// <param name="initKey"/>
        public UserDefinedField(string initValue, string initKey)
            : base(ContactsNameTable.UserDefinedFieldElement, 
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts, initValue)
        {
            this.Attributes.Add(AttributeKey, initKey);   
        }

        //////////////////////////////////////////////////////////////////////
        /// <summary>A simple string value used to name this field. Case-sensitive</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        public string Key
        {
           get 
            {
                return this.Attributes[AttributeKey] as string;
            }
            set
            {
                this.Attributes[AttributeKey] = value;
            }
        }

    }

    /// <summary>
    /// WebSite schema extension 
    /// </summary>
    public class Website : ContactsLink
    {
        /// <summary>
        /// default constructor for WebSite
        /// </summary>
        public Website()
            : base(ContactsNameTable.WebsiteElement,
                   ContactsNameTable.contactsPrefix,
                   ContactsNameTable.NSContacts)
        {
        }
     }
    
}

